package info.niwota.webshot.bm;

import info.niwota.webshot.Bookmarks;
import info.niwota.webshot.R;
import info.niwota.webshot.WebSnapshotActivity;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Browser;
import android.text.ClipboardManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ListView;

public class BookmarksActivity extends Activity implements
		View.OnCreateContextMenuListener {

	private BookmarksAdapter mBookmarksAdapter;

	private static final int BOOKMARKS_SAVE = 1;

	private BookmarkItem mContextHeader;

	private boolean mCanceled = false;

	private boolean mCreateShortcut;

	private static final String INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT";

	private final static String LOGTAG = "browser";

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		// It is possible that the view has been canceled when we get to
		// this point as back has a higher priority
		if (mCanceled) {
			return true;
		}
		AdapterView.AdapterContextMenuInfo i = (AdapterView.AdapterContextMenuInfo) item
				.getMenuInfo();
		// If we have no menu info, we can't tell which item was selected.
		if (i == null) {
			return true;
		}

		switch (item.getItemId()) {
		case R.id.add_context_menu_id:
			addBookmark();
			break;
		case R.id.open_context_menu_id:
			loadUrl(i.position);
			break;
		case R.id.edit_context_menu_id:
			editBookmark(i.position);
			break;
		case R.id.shortcut_context_menu_id:
			final Intent send = createShortcutIntent(getUrl(i.position),
					getBookmarkTitle(i.position), getFavicon(i.position));
			send.setAction(INSTALL_SHORTCUT);
			sendBroadcast(send);
			break;
		case R.id.delete_context_menu_id:
			displayRemoveBookmarkDialog(i.position);
			break;
		case R.id.open_with_context_menu_id:
			launch(i.position);
			break;
		case R.id.send_context_menu_id:
			Browser.sendString(BookmarksActivity.this, getUrl(i.position));
			break;
		case R.id.copy_url_context_menu_id:
			copy(getUrl(i.position));
			break;
		default:
			return super.onContextItemSelected(item);
		}
		return true;
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		AdapterView.AdapterContextMenuInfo i = (AdapterView.AdapterContextMenuInfo) menuInfo;

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.bookmarks_context, menu);

		menu.setGroupVisible(R.id.ADD_MENU, false);
		BookmarkItem b = (BookmarkItem) i.targetView;
		if (mContextHeader == null) {
			mContextHeader = new BookmarkItem(BookmarksActivity.this);
		} else if (mContextHeader.getParent() != null) {
			((ViewGroup) mContextHeader.getParent()).removeView(mContextHeader);
		}
		b.copyTo(mContextHeader);
		menu.setHeaderView(mContextHeader);
	}

	/**
	 * Create a new BookmarksActivity.
	 */
	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);

		setContentView(R.layout.bookmarks_page);
		setTitle(R.string.bookmarks);

		if (Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
			mCreateShortcut = true;
		}

		mBookmarksAdapter = new BookmarksAdapter(this, getIntent()
				.getStringExtra("url"), mCreateShortcut);

		//
		ListView lv = (ListView) findViewById(R.id.list);
		lv.setAdapter(mBookmarksAdapter);
		lv.setDrawSelectorOnTop(false);
		lv.setVerticalScrollBarEnabled(true);
		lv.setOnItemClickListener(mListener);

		if (!mCreateShortcut) {
			lv.setOnCreateContextMenuListener(this);
		}
	}

	private AdapterView.OnItemClickListener mListener = new AdapterView.OnItemClickListener() {
		public void onItemClick(AdapterView<?> parent, View v, int position,
				long id) {
			// It is possible that the view has been canceled when we get to
			// this point as back has a higher priority
			if (mCanceled) {
				android.util.Log.e("browser", "item clicked when dismising");
				return;
			}
			if (!mCreateShortcut) {
				loadUrl(position);
			} else {
				final Intent intent = createShortcutIntent(getUrl(position),
						getBookmarkTitle(position), getFavicon(position));
				setResult(RESULT_OK, intent);
				finish();
			}
		}
	};

	private Intent createShortcutIntent(String url, String title, Bitmap favicon) {
		final Intent i = new Intent();
		final Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, Uri
				.parse(url));
		long urlHash = url.hashCode();
		long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
		shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID, Long
				.toString(uniqueId));
		i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
		i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
		if (favicon == null) {
			i.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
					Intent.ShortcutIconResource.fromContext(
							BookmarksActivity.this,
							R.drawable.ic_launcher_shortcut_browser_bookmark));
		} else {
			Bitmap icon = BitmapFactory.decodeResource(getResources(),
					R.drawable.ic_launcher_shortcut_browser_bookmark);

			// Make a copy of the regular icon so we can modify the pixels.
			Bitmap copy = icon.copy(Bitmap.Config.ARGB_8888, true);
			Canvas canvas = new Canvas(copy);

			// Make a Paint for the white background rectangle and for
			// filtering the favicon.
			Paint p = new Paint(Paint.ANTI_ALIAS_FLAG
					| Paint.FILTER_BITMAP_FLAG);
			p.setStyle(Paint.Style.FILL_AND_STROKE);
			p.setColor(Color.WHITE);

			// Create a rectangle that is slightly wider than the favicon
			final float iconSize = 16; // 16x16 favicon
			final float padding = 2; // white padding around icon
			final float rectSize = iconSize + 2 * padding;
			final float y = icon.getHeight() - rectSize;
			RectF r = new RectF(0, y, rectSize, y + rectSize);

			// Draw a white rounded rectangle behind the favicon
			canvas.drawRoundRect(r, 2, 2, p);

			// Draw the favicon in the same rectangle as the rounded rectangle
			// but inset by the padding (results in a 16x16 favicon).
			r.inset(padding, padding);
			canvas.drawBitmap(favicon, null, r, p);
			i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy);
		}
		// Do not allow duplicate items
		i.putExtra("duplicate", false);
		return i;
	}

	private void addBookmark() {
		Bookmarks.add(this, "", "");
	}

	private void loadUrl(int position) {
		try {
			Intent i = new Intent(this, WebSnapshotActivity.class);
			i.setData(Uri.parse(getUrl(position)));
			finish();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		boolean result = super.onCreateOptionsMenu(menu);
		if (!mCreateShortcut) {
			MenuInflater inflater = getMenuInflater();
			inflater.inflate(R.menu.bookmarks_options, menu);
			return true;
		}
		return result;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.add_options_menu_id:
			addBookmark();
			break;

		default:
			return super.onOptionsItemSelected(item);
		}
		return true;
	}

	private void launch(int position) {
		Bookmarks.open(this, getTitle(position), getUrl(position));
		finish();
	}

	private void editBookmark(int position) {
		Intent i = new Intent(Intent.ACTION_INSERT);
		i.setType("vnd.android.cursor.dir/bookmark");
		i.putExtra("bookmark", getRow(position));
		startActivityForResult(i, BOOKMARKS_SAVE);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case BOOKMARKS_SAVE:
			if (resultCode == RESULT_OK) {
				Bundle extras;
				if (data != null && (extras = data.getExtras()) != null) {
					// If there are extras, then we need to save
					// the edited bookmark. This is done in updateRow()
					String title = extras.getString("title");
					String url = extras.getString("url");
					if (title != null && url != null) {
						mBookmarksAdapter.updateRow(extras);
					}
				} else {
					// extras == null then a new bookmark was added to
					// the database.
					refreshList();
				}
			}
			break;
		default:
			break;
		}
	}

	private void displayRemoveBookmarkDialog(int position) {
		// Put up a dialog asking if the user really wants to
		// delete the bookmark
		final int deletePos = position;
		new AlertDialog.Builder(this).setTitle(R.string.delete_bookmark)
				.setIcon(android.R.drawable.ic_dialog_alert).setMessage(
						getText(R.string.delete_bookmark_warning).toString()
								.replace("%s", getBookmarkTitle(deletePos)))
				.setPositiveButton(R.string.action_ok,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int whichButton) {
								deleteBookmark(deletePos);
							}
						}).setNegativeButton(R.string.action_cancel, null).show();
	}

	public void refreshList() {
		mBookmarksAdapter.refreshList();
	}

	public Bundle getRow(int position) {
		return mBookmarksAdapter.getRow(position);
	}

	public String getTitle(int position) {
		return mBookmarksAdapter.getTitle(position);
	}

	public String getUrl(int position) {
		return mBookmarksAdapter.getUrl(position);
	}

	public Bitmap getFavicon(int position) {
		return mBookmarksAdapter.getFavicon(position);
	}

	private void copy(CharSequence text) {
		try {
			ClipboardManager cb = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
			cb.setText(text);
		} catch (Exception e) {
			Log.e(LOGTAG, "Copy failed", e);
		}
	}

	public String getBookmarkTitle(int position) {
		return mBookmarksAdapter.getTitle(position);
	}

	public void deleteBookmark(int position) {
		mBookmarksAdapter.deleteRow(position);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			mCanceled = true;
			setResult(RESULT_CANCELED);
			finish();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
}
